package pkg

import (
	"fmt"
	"gitee.com/wayjin/fabric-extension/gateway"
	"github.com/gin-gonic/gin"
)

type ChainCodeRequest struct {
	OrgName  string `json:"orgName" binding:"required"`
	PeerID   string `json:"peer" binding:"required"`
	Args     string `json:"args" binding:"required"`
	Username string `json:"username" binding:"required"`
	UserPwd  string `json:"secret" binding:"required"`
}


func installChainCode(svc Service, ctx *gin.Context) {

}

func instantiateChainCode(svc Service, ctx *gin.Context) {

}

func listChainCode(svc Service, ctx *gin.Context) Response {
	peerCtx, _ := svc.getPeerContext("org1", "peer0")
	channelID := ctx.Param("channelid")
	if channelID == "" {
		//ctx.JSON(400, gin.H{"error": "channel id is required"})
		return ResponseError(400, fmt.Errorf("channel id is missing"))
	}

	suite, err := userCtx.CryptoSuite()
	if err != nil {
		//ctx.JSON(500, gin.H{"error": err.Error()})
		return ResponseError(500, err)
	}

	chaincodes, err := gateway.ListChainCodes(suite, channelID, false, peerCtx)
	if err != nil {
		//ctx.JSON(500, gin.H{"error": err.Error()})
		return ResponseError(500, err)
	}
	//ctx.JSON(200, gin.H{"listChaincode": chaincodes})
	return ResponseSuccess(chaincodes)
}

func invokeChainCode(svc Service, ctx *gin.Context) Response {
	channelID := ctx.Param("channelid")
	if channelID == "" {
		//ctx.JSON(400, gin.H{"error": "channelid is required"})
		return ResponseError(400, fmt.Errorf("channelid is required"))
	}
	ccname := ctx.Param("name")
	if ccname == "" {
		//ctx.JSON(400, gin.H{"error": "chaincode name is empty"})
		return ResponseError(400, fmt.Errorf("chaincode name is empty"))
	}
	ccversion := ctx.Param("version")
	if ccversion == "" {
		//ctx.JSON(400, gin.H{"error": "chaincode version is empty"})
		return ResponseError(400, fmt.Errorf("chaincode version is empty"))
	}

	req := ChainCodeRequest{}
	err := ctx.ShouldBindJSON(&req)
	if err != nil {
		//ctx.JSON(500, gin.H{"error":err.Error()})
		return ResponseError(500, err)
	}

	fmt.Println("args:", req.Args)
	spec := gateway.ChaincodeSpec{
		Name: ccname,
		//Version:       ccversion,
		//Lang:          "golang",
		Args: req.Args,
		WaitForEvent: true,
	}
	org, _ := svc.config.PeerOrgs[req.OrgName]
	suite, err := svc.getCryptoSuite(org.MSPID, req.Username, []byte(req.UserPwd)) //userCtx.CryptoSuite()
	if err != nil {
		//ctx.JSON(500, gin.H{"error": err.Error()})
		return ResponseError(500, err)
	}

	odererCtx, _ := svc.getDefaultOrderer()
	peerCtx, _ := svc.getPeerContext(req.OrgName, req.PeerID)
	err = gateway.InvokeChainCode(suite, channelID, spec, odererCtx, peerCtx)
	if err != nil {
		//ctx.JSON(500, gin.H{"error": err.Error()})
		return ResponseError(500, err)
	}

	//ctx.JSON(200, gin.H{"invoke": "success"})
	return ResponseSuccess("invoke success")
}

func queryChainCode(svc Service, ctx *gin.Context) Response {
	channelID := ctx.Param("channelid")
	if channelID == "" {
		//ctx.JSON(400, gin.H{"error": "channel id is required"})
		return ResponseError(400, fmt.Errorf("channelid is missing"))
	}
	ccname := ctx.Param("name")
	if ccname == "" {
		//ctx.JSON(400, gin.H{"error": "chaincode name is empty"})
		return ResponseError(400, fmt.Errorf("chaincode name is missing"))
	}
	ccversion := ctx.Param("version")
	if ccversion == "" {
		//ctx.JSON(400, gin.H{"error": "chaincode version is empty"})
		return ResponseError(400, fmt.Errorf("chaincode version is missing"))
	}

	req := ChainCodeRequest{}
	err := ctx.ShouldBindJSON(&req)
	if err != nil {
		//ctx.JSON(500, gin.H{"error":err.Error()})
		return ResponseError(500, err)
	}
	spec := gateway.ChaincodeSpec{
		Name: ccname,
		Args: req.Args,
	}

	odererCtx, _ := svc.getDefaultOrderer()
	peerCtx, _ := svc.getPeerContext(req.OrgName, req.PeerID)
	org, _ := svc.config.PeerOrgs[req.OrgName]

	suite, err := svc.getCryptoSuite(org.MSPID, req.Username, []byte(req.UserPwd)) //userCtx.CryptoSuite()
	if err != nil {
		//ctx.JSON(500, gin.H{"error": err.Error(), "user":req.Username})
		return ResponseError(500, err)
	}

	resp, err := gateway.QueryChainCode(suite, channelID, spec, odererCtx, peerCtx)
	if err != nil {
		ctx.JSON(500, gin.H{"error": err.Error()})
		return ResponseError(500, err)
	}
	//ctx.JSON(200, gin.H{"result": resp})
	return ResponseSuccess(resp)
}